const handlebars = require('handlebars');
const { isEvent, isPrivate, methodSig, isConstructor, isFunction, parentName, isEnum, optionEquals, isClass, option, isModule } = require('dmd/helpers/ddata');
const arrayify = require('array-back');
const flatten = require('reduce-flatten');
// 当父节点和子节点之间不需要联合符合时忽略父节点
exports.sig = function sig(options) {
    let data;

    if (options.data) {
        data = handlebars.createFrame(options.data || {});
    }

    data.prefix = this.kind === 'constructor' ? 'new' : '';
    data.parent = null;
    data.accessSymbol = null;
    data.name = isEvent.call(this) ? '"' + this.name + '"' : this.name;
    data.methodSign = null;
    data.returnSymbol = null;
    data.returnTypes = null;
    data.suffix = this.isExported ? '⏏' : isPrivate.call(this) ? '℗' : '';
    data.depOpen = null;
    data.depClose = null;
    data.codeOpen = null;
    data.codeClose = null;

    const mSig = methodSig.call(this);
    if (isConstructor.call(this) || isFunction.call(this)) {
        data.methodSign = '(' + mSig + ')';
    } else if (isEvent.call(this)) {
        if (mSig) data.methodSign = '(' + mSig + ')';
    }

    if (!isEvent.call(this)) {
        data.accessSymbol = (this.scope === 'static' || this.scope === 'instance') ? '.' : this.scope === 'inner' ? '~' : '';
        // 当父节点和子节点之间不需要联合符合时忽略父节点
        if (data.accessSymbol) {
            data.parent = parentName.call(this, options);
        }
    }

    if (!isConstructor.call(this)) {
        if (this.returns) {
            data.returnSymbol = '⇒';
            const typeNames = arrayify(this.returns)
                .map(function (ret) {
                    return ret.type && ret.type.names;
                })
                .filter(function (name) {
                    return name;
                });
            if (typeNames.length) {
                data.returnTypes = typeNames.reduce(flatten, []);
            }
        } else if ((this.type || this.kind === 'namespace') && this.kind !== 'event') {
            data.returnSymbol = ':';

            if (isEnum.call(this)) {
                data.returnTypes = ['enum'];
            } else if (this.kind === 'namespace') {
                data.returnTypes = ['object'];
            } else {
                data.returnTypes = this.type.names;
            }
        } else if (this.chainable) {
            data.returnSymbol = '↩︎';
        } else if (this.augments) {
            data.returnSymbol = '⇐';
            data.returnTypes = [this.augments[0]];
        }
    }

    if (this.deprecated) {
        if (optionEquals('no-gfm', true, options) || options.hash['no-gfm']) {
            data.depOpen = '<del>';
            data.depClose = '</del>';
        } else {
            data.depOpen = '~~';
            data.depClose = '~~';
        }
    }

    if (option('name-format', options) && !isClass.call(this) && !isModule.call(this)) {
        data.codeOpen = '`';
        data.codeClose = '`';
    }

    return options.fn(this, { data: data });
};
